package top.cardone.beans;

import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.io.Resource;
import top.cardone.context.ApplicationContextHolder;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * json 文件解析为对象
 *
 * @author yao hai tao
 * @date 2015/5/22
 */
public class JsonFileFactoryBean implements FactoryBean<Object> {
    @lombok.Setter
    private Resource jsonFile;

    @lombok.Setter
    private Resource[] jsonFiles;

    @lombok.Setter
    @lombok.Getter
    private Class<?> objectType;

    @lombok.Setter
    @lombok.Getter
    private boolean singleton;

    private Object object;

    private Object getObjectForJsonFiles() throws Exception {
        if (ArrayUtils.isEmpty(jsonFiles)) {
            return null;
        }

        Map<String, Object> map = Maps.newHashMap();

        for (Resource jsonFile : jsonFiles) {
            if (!jsonFile.exists()) {
                continue;
            }

            String json = FileUtils.readFileToString(jsonFile.getFile(), Charsets.UTF_8);

            Map<String, Object> itemMap = ApplicationContextHolder.getBean(Gson.class).fromJson(json, new TypeToken<LinkedHashMap<String, Object>>() {
            }.getType());

            if (MapUtils.isNotEmpty(itemMap)) {
                map.putAll(itemMap);
            }
        }

        if (objectType == null || Map.class.equals(objectType)) {
            object = map;
        } else {
            String json = ApplicationContextHolder.getBean(Gson.class).toJson(map);

            object = ApplicationContextHolder.getBean(Gson.class).fromJson(json, objectType);
        }

        return object;
    }

    @Override
    public Object getObject() throws Exception {
        if (jsonFile == null) {
            return this.getObjectForJsonFiles();
        }

        if (BooleanUtils.isTrue(singleton) && object != null) {
            return object;
        }

        if (!jsonFile.exists()) {
            return this.getObjectForJsonFiles();
        }

        String json = FileUtils.readFileToString(jsonFile.getFile(), Charsets.UTF_8);

        if (objectType == null) {
            object = ApplicationContextHolder.getBean(Gson.class).fromJson(json, new TypeToken<LinkedHashMap<String, Object>>() {
            }.getType());
        } else {
            object = ApplicationContextHolder.getBean(Gson.class).fromJson(json, objectType);
        }

        return object;
    }
}
